#!/bin/bash
############################################################################
# Copyright (C) 2007 Lawrence Livermore National Security, LLC
# Produced at Lawrence Livermore National Laboratory.
# Written by Jim Garlick <garlick@llnl.gov>.
# UCRL-CODE-235119
# 
# This file is part of nfsroot, a network root file system utility.
# 
# nfsroot is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 2 of the License, or (at your option)
# any later version.
#
# nfsroot is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along
# with nfsroot; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
############################################################################
#
# rc.nfsroot-rbind - nfsroot startup (reverse bind method)
#
# Root is a ramdisk with top level directories bind mounted from a read-only
# NFS root, and configured directories copied into /writeable (ramdisk) 
# and bind mounted back on top if the source directory.
#
export PATH=/bin:/sbin:/usr/bin:/usr/sbin
RAMDIRS="/etc /var"
PREINITPROG=/etc/rc.nfsroot-init
configfile=/etc/sysconfig/nfsroot
if [ -f $configfile ]; then
   . $configfile
fi
prog=rc.nfsroot-rbind

if touch / 2>/dev/null; then
   echo "${prog}: root file system is read-write" >&2
   return 1 
fi

# inlist key [list...]
inlist ()
{
    local key=$1; shift
    while [ $# -gt 0 ]; do
        [ ${key} = $1 ] && return 0
        shift 
    done
    return 1
}

emptydir ()
{
    if [ $(ls -A1 $1 | wc -l) = 0 ]; then
        return 0
    fi
    return 1
}

mnt_options="mode=755,nr_inodes=0${TMPFSMAX:+,size=${TMPFSMAX}}"
echo "${prog}: mounting ramdisk with ${mnt_options}"
if ! mount -n -t tmpfs -o${mnt_options} none /mnt; then
    echo "${prog}: mount failed"
    return 1
fi

# FIXME: ignores any regular files
# FIXME: cleanup on error
skipdirs="/writeable /readonly ${RAMDIRS}"
for el in $(ls -A1); do
    if [ -d ${el} ]; then
        mkdir /mnt/${el} || return 1
        if ! emptydir ${el} && ! inlist "/${el}" ${skipdirs}; then
            mount -n --bind /${el} /mnt/${el} || return 1
        fi
    fi
done

mkdir -p /mnt/writeable
for dir in ${RAMDIRS}; do
    echo "${prog}: copying $dir to ramdisk"
    mkdir -p /mnt/writeable${dir}
    if ! rsync -a ${dir}/ /mnt/writeable${dir} 2>/dev/null; then
        echo "${prog}: copy failed"
        return 1
    fi
    mount -n --bind /mnt/writeable${dir} /mnt${dir}
done

cd /mnt
mkdir -p readonly
pivot_root . readonly || return 1
echo "${prog}: passing control to ${PREINITPROG}" >&2
exec chroot . ${PREINITPROG} "$@" <dev/console >dev/console 2>&1
return 1
